package com.netty.http;

import com.netty.http.anno.RequestMapping;
import com.netty.http.anno.RestController;

import java.io.File;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CompletableFuture;

/**
 * @Author 咕唧
 * @Date 2022/7/7 22:13
 * @Version 1.0
 * 解析注解
 */
public class RequestUtil {
    //保存地址和方法的对应关系
    public static Map<String, Method> url2Method = new HashMap<>();
    //当前地址是用哪个类来执行的
    public static Map<String, Object> url2Object = new HashMap<>();

    /**
     * 处理方法和地址直接的对应关系
     */
    public static void inject() {
        //扫描包所在的所有文件，通过反着加载这些类，判断类上是否有我们定义的注解，如果存在，则加载这些类
        CompletableFuture.runAsync(() -> {
            //通过反射，拿到所有的class
            String pacName = RequestUtil.class.getPackage().getName();
            //System.out.println(pacName);
            //扫描包下的所有文件，通过递归获取，将包名转换为路径
            String dir = pacName.replace(".", "/");

            //获取绝对路径
            URL baseUrl = RequestUtil.class.getClassLoader().getResource(".");
            System.out.println(baseUrl);
            //System.out.println("------" + baseUrl.getProtocol());
            //截取路径

            if (baseUrl.getProtocol().startsWith("file")) {
                String baseUrlPath = baseUrl.getPath();
                File file = new File(baseUrlPath + dir);
                System.out.println("baseUrlPath" + baseUrlPath + dir);
                //遍历文件夹下所有文件
                getFile(file, pacName);
                //看看映射关系
                System.err.println(url2Method);
            }

        });
    }

    public static void getFile(File file, String pacName) {
        //获取所有的文件
        File[] files = file.listFiles();
        //遍历文件，拿到类的全限定名称
        for (File file1 : files) {
            //如果是文件夹，递归，拼接包名
            if (file1.isDirectory()) {
                //System.out.println(pacName+"."+file1.getName());
                getFile(file1, pacName + "." + file1.getName());
            } else {
                try {
                    //System.out.println(file1);
                    String className = pacName + "." + file1.getName().replace(".class", "");
                    //System.err.println(className);
                    //通过反射加载这些类
                    Class<?> aClass = Class.forName(className);
                    //解析这些类，是否包含有我们定义的注解
                    RestController restController = aClass.getAnnotation(RestController.class);

                    //判断类上是否包含注解
                    if (restController != null) {
                        //有注解，创建对象
                        Object controller = aClass.newInstance();
                        //加载地址
                        RequestMapping requestMapping = aClass.getAnnotation(RequestMapping.class);
                        String basePath = "";
                        if (requestMapping != null) {
                            //将类上注解的地址设置为基础地址
                            basePath = requestMapping.value();
                        }
                        //获取方法上的地址
                        Method[] methods = aClass.getMethods();
                        for (Method method : methods) {
                            RequestMapping methodMapping = method.getAnnotation(RequestMapping.class);
                            if (methodMapping != null) {
                                String methodPath = methodMapping.value();
                                //获取到请求的路径
                                String realRequestPath = basePath + methodPath;
                                //地址和路径的关系
                                url2Method.put(realRequestPath, method);
                                //保存方法所在的类对象
                                url2Object.put(realRequestPath, controller);
                            }
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
